﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Threading;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;
using CWB.Common;
using CWB.Web.MVC.Constraints;
using CWB.Web.Configuration;
using CWB.Web.Models.Configuration;
using CWB.Common.Logging;
using CWB.Common.Utilities;
using CWB.Web.ServerTools;

namespace CWB.WebSite
{
    public class CwbWebSiteApp : System.Web.HttpApplication
    {
        private static readonly object syncRoot = new object();
        private readonly static ISysLog log = SysLog.GetLogger(typeof(CwbWebSiteApp));

        private string configurationFolder;
        public static bool isWatcherUpdate;

        public static void RegisterRoutes(RouteCollection routes)
        {
            routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

            routes.MapRoute("image", // Route name
                      "image/{action}", // URL with parameters
                      new { controller = "ImageService", action = "Index" }// Parameter defaults

            );

            routes.MapRoute(
                "BlankRoot", // Route name
                "", // URL with parameters
                new { controller = "login", action = "Index", culture = "zh-tw"}// Parameter defaults
            );

            var cultureRoute = routes.MapRoute("culture", // Route name
                      "{culture}/{controller}/{action}/{id}", // URL with parameters
                      new { controller = "login", action = "Index", culture = "en-gb", id = UrlParameter.Optional }// Parameter defaults

            );

            routes.MapRoute("404-PageNotFound", // Route name
                      "{*url}", // URL with parameters
                      new { controller = "StaticContent", action = "PageNotFound" }// Parameter defaults

            );

            cultureRoute.Constraints.Add("culture", new CultureConstraint(AppConfigManager.LanguageInfos));

        }

        public static void InitializeUiConfigurationManager(string configurationFolderPath)
        {
            CwbWebSiteApp.isWatcherUpdate = false;

            lock (syncRoot)
            {
                AppConfigManager.LanguageInfos = XmlSerializerHelper.ToObj<List<LanguageInfo>>(GetXml(configurationFolderPath, "LanguageInfo.config"));
                AppConfigManager.SystemSetting = XmlSerializerHelper.ToObj<SystemSetting>(GetXml(configurationFolderPath, "SystemSetting.config"));
            }

        }

        protected void Application_Start()
        {
            configurationFolder = HttpContext.Current.Server.MapPath(string.Concat("\\Configuration\\"));
            log4net.Config.XmlConfigurator.ConfigureAndWatch(new FileInfo(configurationFolder + "Log4Net.config"));
            
            log.Debug("Application_Start");
            log.Debug("Configuration.Loading ....");
            InitializeUiConfigurationManager(configurationFolder);

            //AreaRegistration.RegisterAllAreas();
            RegisterRoutes(RouteTable.Routes);

            //set controller factory
            ControllerBuilder.Current.SetControllerFactory(typeof(LanguageControllerFactory));

            //for watching updated config file.
            AddFileWatcher(configurationFolder, "watcher", () =>
            {
                if (isWatcherUpdate)
                {
                    InitializeUiConfigurationManager(configurationFolder);
                }
            });
            if (AppConfigManager.SystemSetting.EnableColudeEmail)
            {
#if !DEBUG
                EnvInfo.SendEmailToAdminstratorWhenStartService();
#endif
            }
            log.Debug("Application_Start Finish");
        }

        private static string GetXml(string configurationFolderPath, string fileName)
        {
            return File.ReadAllText(configurationFolderPath + fileName);
        }

        //for watching updated file.
        private void AddFileWatcher(string configurationFolder, string watcherName, Action callBackMethod)
        {
            Application.Add(watcherName, new FileSystemWatcher(configurationFolder));
            FileSystemWatcher watcher = (FileSystemWatcher)Application[watcherName];
            watcher.EnableRaisingEvents = true;
            watcher.IncludeSubdirectories = true;
            watcher.NotifyFilter = NotifyFilters.FileName | NotifyFilters.LastWrite | NotifyFilters.CreationTime;
            watcher.Changed += delegate
            {
                (new Thread(new ThreadStart(delegate
                {
                    watcher.ToString();
                    isWatcherUpdate = true;
                    Thread.Sleep(5000);
                    callBackMethod();
                }))).Start();
            };
        }


    }
}